package com.practice.service.user.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.practice.common.result.PageResult;
import com.practice.common.result.Result;
import com.practice.common.utils.JwtUtil;
import com.practice.mapper.admin.AdvimgMapper;
import com.practice.mapper.admin.ConfigMapper;
import com.practice.mapper.admin.LinkMapper;
import com.practice.mapper.user.*;
import com.practice.pojo.admin.dto.ConfigDTO;
import com.practice.pojo.admin.entity.Advimg;
import com.practice.pojo.admin.entity.Config;
import com.practice.pojo.admin.entity.Link;
import com.practice.pojo.admin.vo.AllConfigVO;
import com.practice.pojo.user.dto.PageQueryDTO;
import com.practice.pojo.user.dto.RegisterMessageDTO;
import com.practice.pojo.user.entity.*;
import com.practice.pojo.user.vo.*;
import com.practice.service.user.IndexService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneOffset;
import java.util.HashMap;
import java.util.List;

import static com.practice.common.constant.ConfigConstant.*;

@Service
public class IndexServiceImpl implements IndexService {
    
    @Autowired
    private CateMapper cateMapper;
    @Autowired
    private LinkMapper linkMapper;
    @Autowired
    private TagMapper tagMapper;
    @Autowired
    private AdvimgMapper advimgMapper;
    
    @Autowired
    private ArticleMapper articleMapper;

    @Autowired
    private ConfigFragmentMapper configFragmentMapper;

    @Autowired
    private ConfigMapper configMapper;

    @Override
    public Result index() {
        List<Cate> allCate = cateMapper.selectList(null);
        List<Link> allLink = linkMapper.selectList(null);
        List<Tag> allTag = tagMapper.selectList(null);

        QueryWrapper<Advimg> bannerWrapper = new QueryWrapper<>();
        bannerWrapper.eq("advimgpos", 15);
        List<Advimg> banner = advimgMapper.selectList(bannerWrapper);

        QueryWrapper<Advimg> showBannerWrapper = new QueryWrapper<>();
        showBannerWrapper.eq("advimgpos", 13).or().eq("advimgpos", 12);
        List<Advimg> showBanner = advimgMapper.selectList(showBannerWrapper);

        QueryWrapper<Advimg> sideBannerWrapper = new QueryWrapper<>();
        sideBannerWrapper.eq("advimgpos", 14);
        List<Advimg> sideBanner = advimgMapper.selectList(sideBannerWrapper);

        RConfig rConfig = getrConfig();

        IndexVO indexVO = new IndexVO().builder()
                .allCate(allCate)
                .allLink(allLink)
                .allTag(allTag)
                .banner(banner)
                .Config(rConfig)
                .showBanner(showBanner)
                .sideBanner(sideBanner)
                .build();
        return Result.success(indexVO);
    }

    private RConfig getrConfig() {
        //1 封装若干CNK
        //1.1 封装baseConfigCNK
        //1.1.1 封装siteConfigDN
        DN siteConfigDN = fillDN(TABLE_VALUE_BASE, GROUP_VALUE_SITE_CONFIG);
        //1.1.2 bottomInformationDN
        DN bottomInformationDN = fillDN(TABLE_VALUE_BASE, GROUP_VALUE_SITE_CONFIG);
        //1.1.3 otherConfigDN
        DN otherConfigDN = fillDN(TABLE_VALUE_BASE, GROUP_VALUE_SITE_CONFIG);

        CNK baseConfigCNK = fillCNK(CollUtil.newArrayList(siteConfigDN,bottomInformationDN,otherConfigDN),
                "基础配置", "desc");
        //1.2 封装systemConfigCNK
        //1.2.1 封装systemConfigDN
        DN systemConfigDN = fillDN(TABLE_VALUE_SYSTEM, GROUP_VALUE_SYSTEM_CONFIG);
        CNK systemConfigCNK = fillCNK(CollUtil.newArrayList(systemConfigDN),
                "系统配置", "system");
        //1.3 封装otherConfigCNK
        //1.3.1 封装noticAnnouncementDN
        DN noticAnnouncementDN = fillDN(TABLE_VALUE_CUSTOM, GROUP_VALUE_NOTIC_ANNOUNCEMENT);
        //1.3.2 封装frontIMGDN
        DN frontIMGDN = fillDN(TABLE_VALUE_CUSTOM, GROUP_VALUE_FRONT_IMG);
        CNK otherConfigCNK = fillCNK(CollUtil.newArrayList(noticAnnouncementDN,frontIMGDN),
                "其他设置", "custom");

        RConfig rConfig = new RConfig();
        List<Config> configList = configFragmentMapper.selectList(null);
        List<ConfigFragment> allData = BeanUtil.copyToList(configList, ConfigFragment.class);
        
        rConfig.setAllData(allData);
        rConfig.setList(CollUtil.newArrayList(baseConfigCNK,systemConfigCNK,otherConfigCNK));
        return rConfig;
    }
    

    /**
     * 根据tab_value、global_value值分组，可以装填所有的DN
     * @param tabValue
     * @param groupValue
     * @return
     */
    public DN fillDN(String tabValue,String groupValue){
        QueryWrapper<Config> DNWrapper = new QueryWrapper<>();
        DNWrapper.eq("tab_value", tabValue)
                .eq("group_value", groupValue);
        List<Config> bottomInformationList = configMapper.selectList(DNWrapper);
        DN DN = new DN();
        DN.setData(bottomInformationList);
        DN.setName(groupValue);
        return DN;
    }

    /**
     * 封装所有CNK
     * @param DNList
     * @param name
     * @param key
     * @return
     */
    public CNK fillCNK(List<DN> DNList,String name,String key) {
        CNK CNK = new CNK();
        CNK.setChildren(DNList);
        CNK.setName(name);
        CNK.setKey(key);
        return CNK;
    }
    
    @Override
    public Result news(PageQueryDTO dto) {
        //1 创建IPage分页对象,设置分页参数
        IPage<Article> page=new Page<>(dto.getPage(),dto.getLimit());
        //2 执行分页查询
        articleMapper.selectPage(page,null);
        PageResult list = PageResult.builder()
                .count(page.getTotal())
                .totalPages(page.getPages())
                .pageSize(page.getSize())
                .currentPage(page.getCurrent())
                .data(page.getRecords())
                .build();
        
        //计算24小时更新的数量
        LocalDateTime yestday =LocalDateTime.of(LocalDate.now().minusDays(1), LocalTime.MIN);
        //获取毫秒数
        Long yestdayMilliSecond = yestday.toInstant(ZoneOffset.of("+8")).toEpochMilli();

        //计算7天更新的数量
        LocalDateTime preWeek =LocalDateTime.of(LocalDate.now().minusDays(7), LocalTime.MIN);
        //获取毫秒数
        Long preWeekMilliSecond = preWeek.toInstant(ZoneOffset.of("+8")).toEpochMilli();
        
        Long numDay = articleMapper.selectCount(new QueryWrapper<Article>().ge("create_date", yestdayMilliSecond));

        Long numWeek = articleMapper.selectCount(new QueryWrapper<Article>().ge("create_date", preWeekMilliSecond));
        //计算一周更新的数量
        NewsVO vo = new NewsVO().builder()
                .desc("首页大列表")
                .list(list)
                .numDay(numDay)
                .numWeek(numWeek)
                .build();
        return Result.success(vo);
    }

    @Override
    public Result list(PageQueryDTO dto) {
        //1 创建IPage分页对象,设置分页参数
        IPage<Article> page=new Page<>(dto.getPage(),dto.getLimit());
        //2 执行分页查询
        articleMapper.selectPage(page,new QueryWrapper<Article>().eq("cateid", dto.getCateid()));
        PageResult list = PageResult.builder()
                .count(page.getTotal())
                .totalPages(page.getPages())
                .pageSize(page.getSize())
                .currentPage(page.getCurrent())
                .data(page.getRecords())
                .build();

        //计算24小时更新的数量
        LocalDateTime yestday =LocalDateTime.of(LocalDate.now().minusDays(1), LocalTime.MIN);
        //获取毫秒数
        Long yestdayMilliSecond = yestday.toInstant(ZoneOffset.of("+8")).toEpochMilli();

        //计算7天更新的数量
        LocalDateTime preWeek =LocalDateTime.of(LocalDate.now().minusDays(7), LocalTime.MIN);
        //获取毫秒数
        Long preWeekMilliSecond = preWeek.toInstant(ZoneOffset.of("+8")).toEpochMilli();

        Long numDay = articleMapper.selectCount(new QueryWrapper<Article>().ge("create_date", yestdayMilliSecond));

        Long numWeek = articleMapper.selectCount(new QueryWrapper<Article>().ge("create_date", preWeekMilliSecond));
        //计算一周更新的数量
        NewsVO vo = new NewsVO().builder()
                .desc("首页大列表")
                .list(list)
                .numDay(numDay)
                .numWeek(numWeek)
                .build();
        return Result.success(vo);
    }

    @Autowired
    private UUserMapper uUserMapper;
    
    @Override
    public Result reg(RegisterMessageDTO dto) {
        //根据dto复制给User
        User user = BeanUtil.copyProperties(dto, User.class);
        user.setUsername(dto.getMobile().toString());
        user.setPassword(DigestUtils.md5DigestAsHex(dto.getPassword().getBytes()));
        user.setDefaultData("1");
        //执行插入语句
        uUserMapper.insert(user);
        //封装返回数据
        UserVO userVO = BeanUtil.copyProperties(user, UserVO.class);
        return Result.success(userVO);
    }
    
    @Override
    public Result login(RegisterMessageDTO dto) {
        //加密密码
        String password = DigestUtils.md5DigestAsHex(dto.getPassword().getBytes());
        //与数据库作对比
        User user = uUserMapper.selectOne(new LambdaQueryWrapper<User>().
                eq(User::getMobile, dto.getMobile()).eq(User::getPassword, password));
        //判断登录逻辑
        if (user != null) {
            String token = JwtUtil.getToken(user.getId());
            HashMap<Object, Object> map = new HashMap<>();
            map.put("token", token);
            return Result.success(map);
        }
        return Result.error("密码错误");
    }
    @Override
    public Result hot() {
        //查询hot数据
        List<ArticalHotVO> voList = articleMapper.hot();
        //封装数据
        HashMap<String, Object> map = new HashMap<>();
        map.put("desc", "热门数据");
        map.put("list", voList);
        //返回数据
        return Result.success(map);
    }

    @Override
    public Result recommend() {
        //查询recommend数据
        List<ArticalHotVO> voList = articleMapper.recommend();
        //封装数据
        HashMap<String, Object> map = new HashMap<>();
        map.put("desc", "最新推荐");
        map.put("list", voList);
        //返回数据
        return Result.success(map);
    }

    @Override
    public Result show(Long id) {
        //查询下一个   
        LambdaQueryWrapper<Article> nextWrapper = new LambdaQueryWrapper<>();
        nextWrapper.gt(Article::getId, id)
                .orderBy(true, true, Article::getId)
                .last("limit 1");
        Article next = null;
        next = articleMapper.selectOne(nextWrapper);

        LambdaQueryWrapper<Article> prevWrapper = new LambdaQueryWrapper<>();
        prevWrapper.lt(Article::getId, id)
                .orderBy(true, false, Article::getId)
                .last("limit 1");
        Article prev = null;
        prev = articleMapper.selectOne(prevWrapper);
        
        /*LambdaQueryWrapper<Article> maxwrapper = new LambdaQueryWrapper<>();
        maxwrapper.orderByDesc(Article::getId).last("limit 1");
        Long maxId = articleMapper.selectOne(maxwrapper).getId();

        
        for (Long i = id+1; i <= maxId; i++) {
            next = articleMapper.selectById(i);
            if (next != null) {
                break;
            }
        }
        //查询上一个    
        LambdaQueryWrapper<Article> minwrapper = new LambdaQueryWrapper<>();
        minwrapper.orderByAsc(Article::getId).last("limit 1");
        Long minId = articleMapper.selectOne(minwrapper).getId();
        Article prev = null;
        for (Long i = id-1; i >= minId; i--) {
            prev = articleMapper.selectById(i);
            if (prev != null) {
                break;
            }
        }*/
        //当前的
        Article info = articleMapper.selectById(id);
        if (next == null) {
            next = info;
        }
        if (prev == null) {
            prev = info;
        }
        //推荐的
        List<ArticalHotVO> voList = articleMapper.recommend();
        
        return Result.success(new ShowVO(
                next,
                prev,
                voList,
                info
        ));
    }

    //系统配置------------------------------
    @Override
    public Result all() {
        //封装list
        //封装allData
        RConfig rConfig=getrConfig();
        List<CNK> list = rConfig.getList();
        List<ConfigFragment> allData = rConfig.getAllData();
        //封装configForm
        LambdaQueryWrapper<Config> keywrapper = new LambdaQueryWrapper<>();
        keywrapper.select(Config::getAttrKey);
        List<Config> key = configMapper.selectList(keywrapper);
        
        LambdaQueryWrapper<Config> valuewrapper = new LambdaQueryWrapper<>();
        valuewrapper.select(Config::getAttrValue);
        List<Config> value = configMapper.selectList(valuewrapper);
        HashMap<String, String> configForm = new HashMap<>();
        for (int i = 0; i < key.size(); i++) {
            configForm.put(key.get(i).getAttrKey(), value.get(i).getAttrValue());
        }
        //封装configRules
        LambdaQueryWrapper<Config> siteNameWrapper = new LambdaQueryWrapper<>();
        siteNameWrapper.eq(Config::getAttrKey,"site_name");
        Config config = configMapper.selectOne(siteNameWrapper);
        HashMap<String, Object> configRules = new HashMap<>();
        configRules.put("site_name",config.getValidator());
        return Result.success(new AllConfigVO(
                list,
                allData,
                configForm,
                configRules
        ));
    }

    @Override
    public Result update(List<ConfigDTO> dto) {
        for (int i = 0; i < dto.size(); i++) {
            Config config = new Config();
            config.setId(dto.get(i).getId());
            config.setAttrKey(dto.get(i).getAttr_key());
            config.setAttrValue(dto.get(i).getAttr_value());
            configMapper.updateById(config);
        }
        return Result.success();
    }

}
